//
// Created by ByteFlow on 2019/7/10.
//

#include <GLUtils.h>
#include <LogUtil.h>
#include "TextureMapSample.h"
//纹理映射贴图的一般步骤.
// 生成纹理，编译链接着色器程序
//  确定纹理坐标及对应的顶点坐标
//  加载图像数据到纹理，加载纹理坐标和顶点坐标到着色器程序
//	绘制
TextureMapSample::TextureMapSample()
{
	//生成一个纹理，将纹理 id 赋值给 m_TextureId
	m_TextureId = 0;

}

TextureMapSample::~TextureMapSample()
{
	//析构函数 释放内存资源.
	NativeImageUtil::FreeNativeImage(&m_RenderImage);
}
// 生成纹理，编译链接着色器程序
void TextureMapSample::Init()
{
	CreateTexture();
    //eeeeee 顶点着色器绘制图形.
	char vShaderStr[] =
			"#version 300 es                            \n"
			"layout(location = 0) in vec4 a_position;   \n"
			"layout(location = 1) in vec2 a_texCoord;   \n"
			"out vec2 v_texCoord;                       \n"
			"void main()                                \n"
			"{                                          \n"
			"   gl_Position = a_position;               \n"
			"   v_texCoord = a_texCoord;                \n"
			"}                                          \n";
    //光栅化是将图元转化为一组二维片段的过程,这些片段由片段着色器处理.
    //eeeeee 创建片段着色器.给二维片段着色.
	// texture() 为内置的采样函数，v_texCoord 为顶点着色器传进来的纹理坐标
	// 根据纹理坐标对纹理进行采样，输出采样的 rgba 值（4维向量）
	//这一段写法??? 可以写成shader小程序加载进来.
	char fShaderStr[] =
			"#version 300 es                                     \n"
			"precision mediump float;                            \n"
			"in vec2 v_texCoord;                                 \n"
			"layout(location = 0) out vec4 outColor;             \n"
			"uniform sampler2D s_TextureMap;                     \n"
			"void main()                                         \n"
			"{                                                   \n"
			"  outColor = texture(s_TextureMap, v_texCoord);     \n"
			"}                                                   \n";
    //创建项目在项目上运行 顶点着色器和片段着色器.
	m_ProgramObj = GLUtils::CreateProgram(vShaderStr, fShaderStr, m_VertexShader, m_FragmentShader);
	if (m_ProgramObj)
	{
        //glGetUniformLocation返回一个整数，表示程序对象中特定统一变量的位置（序号）。 name必须是不包含空格的空终止字符串。 name必须是程序中的活动统一变量名，它不能是结构，也不能是结构数组或向量或矩阵的子组件。 如果name与程序中的活动统一变量不对应，或者name以保留前缀“gl_”开头，则此函数返回-1。
		//版权声明：本文为CSDN博主的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。
		m_SamplerLoc = glGetUniformLocation(m_ProgramObj, "s_TextureMap");
        LOGCATE("TextureMapSample::Init create program success");
	}
	else
	{
		LOGCATE("TextureMapSample::Init create program fail");
	}

}

void TextureMapSample::Draw()
{
	LOGCATE("eeeeeeee TextureMapSample::Draw()");

	if(m_ProgramObj == GL_NONE || m_TextureId == GL_NONE) return;

	//设置激活的纹理单元
	glActiveTexture(GL_TEXTURE0);
	//将纹理 m_TextureId 绑定到类型 GL_TEXTURE_2D 纹理
	glBindTexture(GL_TEXTURE_2D, m_TextureId);
	//加载 RGBA 格式的图像数据
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_RenderImage.width, m_RenderImage.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_RenderImage.ppPlane[0]);
	glBindTexture(GL_TEXTURE_2D, GL_NONE);

	//glViewport(0, 0, m_RenderImage.width, m_RenderImage.height);
    //eeeeeee 4个纹理贴图对应的坐标系
	GLfloat verticesCoords[] = {
			-1.0f,  0.82f, 0.0f,  // Position 0
			-1.0f, -0.82f, 0.0f,  // Position 1
			 1.0f, -0.82f, 0.0f,  // Position 2
			 1.0f,  0.82f, 0.0f,  // Position 3
	};
    // 4 个纹理坐标分别为
	GLfloat textureCoords[] = {
			0.0f,  0.0f,        // TexCoord 0
			0.0f,  1.0f,        // TexCoord 1
			1.0f,  1.0f,        // TexCoord 2
			1.0f,  0.0f         // TexCoord 3
	};

	GLushort indices[] = { 0, 1, 2, 0, 2, 3 };

	// Use the program object
	glUseProgram (m_ProgramObj);

	//  glVertexAttribPointer 指定了渲染时索引值为 index 的顶点属性数组的数据格式和位置。 Load the vertex position 加载顶点的位置
	glVertexAttribPointer (0, 3, GL_FLOAT,
							GL_FALSE, 3 * sizeof (GLfloat), verticesCoords);
	// Load the texture coordinate 加载纹理坐标
	glVertexAttribPointer (1, 2, GL_FLOAT,
							GL_FALSE, 2 * sizeof (GLfloat), textureCoords);

	glEnableVertexAttribArray (0);
	glEnableVertexAttribArray (1);

	// Bind the RGBA map
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, m_TextureId);

	// Set the RGBA map sampler to texture unit to 0
	glUniform1i(m_SamplerLoc, 0);

	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);

	LOGCATE("eeeeeeee TextureMapSample::onDraw over()");

}
// eeeeee 通过NativeImage 进行关联.
void TextureMapSample::LoadImage(NativeImage *pImage)
{
	LOGCATE("eeeeeee TextureMapSample::LoadImage pImage = %p", pImage->ppPlane[0]);
	if (pImage)
	{
		m_RenderImage.width = pImage->width;
		m_RenderImage.height = pImage->height;
		m_RenderImage.format = pImage->format;
        //eeeeee 底层加载Image 图片方法
        NativeImageUtil::CopyNativeImage(pImage, &m_RenderImage);
	}

}

void TextureMapSample::CreateTexture()
{
	//create RGBA texture 设置激活的纹理单元（texture unit）
	glActiveTexture(GL_TEXTURE0);
	// 绑定纹理目标(一个或多个)到纹理单元
	glGenTextures(1, &m_TextureId);
	glBindTexture(GL_TEXTURE_2D, m_TextureId);
	//设置纹理 S 轴（横轴）的拉伸方式为截取
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	//设置纹理采样方式
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

}

void TextureMapSample::DeleteTexture()
{
	if (m_TextureId)
	{
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, GL_NONE);
		glDeleteTextures(1, &m_TextureId);
		m_TextureId = 0;
	}

}
